﻿// ReSharper disable InconsistentNaming
using System;
using System.Collections.Generic;
using CI.Interfaces;
using CI.Mesopotamia;
using CI.Organism;
using NUnit.Framework;
using Rhino.Mocks;

namespace Mesopotamia.UnitTests
{
    [TestFixture]
    public class SimpleSimulationRestrictionsTests
    {
        private SimpleSimulationRestrictions _ssr;
        private IHostingEnvironment _hostingEnvironment;
        private IHostingEnvironmentPhysical _hostingEnvironmentPhysical;
        private OrganismCollection _organisms;
        private const int MaxEntitySupported = 3;

        [SetUp]
        public void Setup()
        {
            _ssr = new SimpleSimulationRestrictions();
            _organisms = new OrganismCollection();

            _hostingEnvironmentPhysical = MockRepository.GenerateMock<IHostingEnvironmentPhysical>();
            _hostingEnvironmentPhysical.Stub(x => x.MaxEntitysSupported).Return(MaxEntitySupported);


            _hostingEnvironment = MockRepository.GenerateMock<IHostingEnvironment>();
            _hostingEnvironment.Stub(x => x.Organisms).Return(_organisms);
            _hostingEnvironment.Stub(x => x.HostingEnvironmentPhysical).Return(_hostingEnvironmentPhysical);
        }


        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_AliveListCulledBornWithNeural_Equal()
        {
            CullAndCheckList(_organisms.Alive, _organisms.AliveAdd, true, MockRepository.GenerateMock<INeuralSystem>());
        }

        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_DeadListCulledBornWithNeural_Equal()
        {
            CullAndCheckList(_organisms.Dead, _organisms.DeadAdd, true, MockRepository.GenerateMock<INeuralSystem>());
        }

        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_AliveListCulledNotBornWithNeural_NotEqual()
        {
            CullAndCheckList(_organisms.Alive, _organisms.AliveAdd, false, MockRepository.GenerateMock<INeuralSystem>());
        }

        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_DeadListCulledNotBornWithNeural_NotEqual()
        {
            CullAndCheckList(_organisms.Dead, _organisms.DeadAdd, false, MockRepository.GenerateMock<INeuralSystem>());
        }

        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_AliveListCulledBornWithoutNeural_Equal()
        {
            CullAndCheckList(_organisms.Alive, _organisms.AliveAdd, true,null);
        }

        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_DeadListCulledBornWithoutNeural_Equal()
        {
            CullAndCheckList(_organisms.Dead, _organisms.DeadAdd, true,null);
        }

        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_AliveListCulledNotBornWithoutNeural_NotEqual()
        {
            CullAndCheckList(_organisms.Alive, _organisms.AliveAdd, false,null);
        }

        [Test]
        public void CullOrganismsIfOverMaxEntitysSupported_DeadListCulledNotBornWithoutNeural_NotEqual()
        {
            CullAndCheckList(_organisms.Dead, _organisms.DeadAdd, false,null);
        }


        private void CullAndCheckList(SynchronizedCollection<IOrganism> organisms, Action<IOrganism> action, bool born, INeuralSystem neuralSystem)
        {

            for (int i = 0; i < MaxEntitySupported * MaxEntitySupported; i++)
            {
                var organism = new MockedOrganism(_organisms, born, neuralSystem);
                action(organism);
            }

            _hostingEnvironmentPhysical.Stub(x => x.EntitysConsumed).Return(organisms.Count);

            _ssr.CullOrganismsIfOverMaxEntitysSupported(_hostingEnvironment);

            if (born)
                Assert.AreEqual(MaxEntitySupported, organisms.Count);
            else
                Assert.AreNotEqual(MaxEntitySupported, organisms.Count);
        }
    }
}
